#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <map>
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <map>
#include <vector>
#include <errno.h>
#include "Point.h"
#include "Constantes.h"
#include <math.h>

#include "Constantes.h"
#include "Paquet.h"
#include "Adresse.h"

using namespace std;


struct liaison{
	int premierSommet;
	int secondSommet;
};


//! La classe ProcessusPerte a pour but de perdre aléatoirement les paquets.
/*!
 Le processus aléatoire consiste a attendre qu'un client envoie un paquet et dès qu'un client l'a envoyé, le processus aléatoire va perdre aléatoirement le paquet envoyé.
 */
class ProcessusPerte {
	
private:
	
	vector<liaison> liaisonsCasses;
	
    //! Socket du ProcessusPerte.
    int socketEcoute;
    //! Taille de l'adresse du client.
    socklen_t tailleAdresseEmetteur;
    //! Adresse du ProcessusPerte.
    struct sockaddr_in myAdresse;
    //! Adresse de l'emetteur.
    struct sockaddr_in adresseEmetteur;
    //! Adresse du receveur.
    struct sockaddr_in adresseReceveur;
    
    //! Thread s'occupant du client.
    pthread_t threadGestionClient;
	
	//! Thread s'occupant de la casse des liaisons
    pthread_t threadGestionCasseLiaison;
    
    //! Message que l'on veut transmettre
    char message[TAILLE_MESSAGE];
    //! Table permettant de faire la correspondance entre le numéro des routeurs et leurs adresses.
    map<int, Adresse> adresses;
	
	//! Graphe des liaisons entre les routeurs.
    float **graphe;
    
    
public:
    
    //! Constructeur basic de la classe ProcessusPerte.
    ProcessusPerte();
    
    //! Destructeur de la classe ProcessusPerte.
    ~ProcessusPerte();
    
    //! Initialise le processus aléatoire.
    /*!
     Crée et initialise de la socket d'écoute du processus aléatoire.
     */
    void init();
    
    
    //! Lance le processus aléatoire.
    /*! 
     Le lancement du processus aléatoire consiste a attend qu'un client envoie un paquet et dès qu'un client l'a envoyé, le processus aléatoire lance un thread qui va traiter la demande du client.
     */
    void lancement();
    
    //! Retourne vrai si le paquet ne doit pas être envoyé (perdu), faux sinon.
    /*!
     \return Vrai si le paquet doit être perdu, faux sinon.
     */
    bool perdrePaquet();
    
    //! Gère la demande du client.
    /*!
     S'occupe d'envoyer ou non le paquet du client à la destination demandée par le client.
     */
    void gestionClient();
    
    //! Traite les messages envoyé par le serveur.
    /*!
     Les messages envoyés par le serveur permettent au processus aléatoire de mettre à jours sa table lui permettant de savoir à quelle adresse se trouve les routeurs.
     */
    void gestionServeur();
    
    //! Lance l'execution du thread permettant de traiter les messages envoyés au processus aléatoire par les clients.
    /*!
     \param arg 
     */
    static void *runGestionClient(void *arg);
    
    //! Envoie un message au routeur demande.
    /*!
     \param message le message que doit envoyer le processus aléatoire au routeur.
     \param sommet le routeur destinataire qui doit recevoir le message.
     */
	void envoieMessageSommet(char * message,int sommet);
	
	//! Verifie si les sommets font partie d'une liaisons qui est cassé.
    /*!
     \param premier sommet de la liaison.
     \param second sommet de la liaison.
     */
	bool isLiaisonCasse(int premierSommet, int secondSommet);
	
	//! Permet d'ouvrir le fichier permettant de construire le graphe
    /*!
     \param url url du fichier
     */
	void ouvrirFichier(string url);
	
	
	//! Lance l'execution du thread permettant de traiter les casses de liaisons
    /*!
     \param arg 
     */
	static void* runGestionCasseLiaison(void *arg);
	
	
	//! Gère la casse des liaisons.
    /*!
     
     */
	void gestionCasseLiaison();
};